package com.gengzp.common.config;

import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName ThreadPoolConfig
 * @Description 饿汉式单例线程池配置类（项目启动即初始化）
 * @Author gengzp
 * @Date 2025/9/15 20:30
 */
@Component
public class ThreadPoolConfig {

    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolConfig.class);

    /**
     * 核心线程数
     */
    private static final int CORE_POOL_SIZE = 30;

    /**
     * 最大线程数
     */
    private static final int MAX_POOL_SIZE = 300;

    /**
     * 空闲线程存活时间（默认60秒）
     */
    private static final int KEEP_ALIVE_SECONDS = 60;

    /**
     * 阻塞队列容量
     */
    private static final int QUEUE_CAPACITY = 512;

    /**
     * 线程名称前缀
     */
    private static final String THREAD_NAME_PREFIX = "custom-thread-";

    /**
     * 业务线程池单例（类加载时初始化，天然线程安全）
     */
    private static ThreadPoolExecutor threadPoolExecutorInstance;

    /**
     * 定时任务线程池单例
     */
    private static ThreadPoolExecutor scheduledTaskThreadPoolInstance;

    @PostConstruct
    public void init() {
        // 自定义线程工厂，设置线程名称和属性
        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, THREAD_NAME_PREFIX + threadNumber.getAndIncrement());
                // 非守护线程（避免主线程退出导致线程池强制关闭）
                thread.setDaemon(false);
                // 正常优先级
                thread.setPriority(Thread.NORM_PRIORITY);
                return thread;
            }
        };

        // 创建线程池
        threadPoolExecutorInstance = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_SECONDS,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(QUEUE_CAPACITY), // 有界队列，避免OOM
                threadFactory,
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略：提交任务的线程自己执行
        );
        logger.info("业务程序线程池初始化完成：核心线程数={}, 最大线程数={}, 队列容量={}",
                CORE_POOL_SIZE, MAX_POOL_SIZE, QUEUE_CAPACITY);

        scheduledTaskThreadPoolInstance = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_SECONDS,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(QUEUE_CAPACITY), // 有界队列，避免OOM
                threadFactory,
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略：提交任务的线程自己执行
        );
        logger.info("定时任务专用线程池初始化完成：核心线程数={}, 最大线程数={}, 队列容量={}",
                CORE_POOL_SIZE, MAX_POOL_SIZE, QUEUE_CAPACITY);
    }

    /**
     * 私有构造方法，禁止外部实例化
     */
    private ThreadPoolConfig() {
    }

    /**
     * 获取业务程序线程池实例（直接返回预初始化的实例）
     */
    public static ThreadPoolExecutor getInstance() {
        return threadPoolExecutorInstance;
    }

    /**
     * 获取定时任务专用线程池
     */
    public static ThreadPoolExecutor getScheduledTaskThreadPool() {
        return scheduledTaskThreadPoolInstance;
    }

    /**
     * 优雅关闭线程池
     */
    public static void shutdown(ThreadPoolExecutor threadPoolExecutorInstance) {
        if (!threadPoolExecutorInstance.isShutdown()) {
            // 停止接收新任务，等待已提交任务完成
            threadPoolExecutorInstance.shutdown();
            try {
                // 等待60秒，若未完成则强制关闭
                if (!threadPoolExecutorInstance.awaitTermination(60, TimeUnit.SECONDS)) {
                    threadPoolExecutorInstance.shutdownNow(); // 强制关闭，中断正在执行的任务
                    logger.warn("线程池强制关闭");
                } else {
                    logger.info("线程池优雅关闭完成");
                }
            } catch (InterruptedException e) {
                // 等待过程中被中断，强制关闭
                threadPoolExecutorInstance.shutdownNow();
                logger.warn("线程池关闭被中断", e);
            }
        }
    }

}
